package com.cloneoner.utils
{
	import flash.geom.Point;
	
	
	/**
	 * @author Thibault Loup
	 */
	public class ClEuclideanVector
	{
		
		
		// __________________________________________________________
		// -										 	  CONSTRUCTOR
		public function ClEuclideanVector( pEndPoint:Point)
		{
			_position = pEndPoint;
		}
		
		// __________________________________________________________
		// -										  GETTER / SETTER
		
		public function get position():Point
		{
			return _position;
		}
		
		public function get magnitude():Number
		{
			return Math.sqrt((_position.x * _position.x) + ( _position.y * _position.y));
		}
		
		public function get angle():Number
		{
			var a:Number = Math.atan2(_position.y, _position.x);
			
			return a < 0 ? a+Math.PI*2 : a;
		}
		
		
		// __________________________________________________________
		// -										  PUBLICS METHODS
		
		public function inverse():ClEuclideanVector
		{
			return new ClEuclideanVector(new Point(-_position.x, -_position.y));
		}
		
		public function sum( pVector:ClEuclideanVector):ClEuclideanVector
		{
			_position.x += pVector.position.x;
			_position.y += pVector.position.y;
			
			return this;
		}
		
		public function substract( pVector:ClEuclideanVector):ClEuclideanVector
		{
			_position.x -= pVector.position.x;
			_position.y -= pVector.position.y;
			
			return this;
		}
		
		public function multiply( pNumber:Number ):ClEuclideanVector
		{
			_position.x *= pNumber;
			_position.y *= pNumber;
			
			return this;
		}
		
		public function dot( pVector:ClEuclideanVector):Number
		{
			return ( _position.x * pVector.position.x) + ( _position.y * pVector.position.y);
		}
		
		public function angleBetween( pVector:ClEuclideanVector):Number
		{
			return Math.cos(dot(pVector) / ( magnitude * pVector.magnitude));
		}
		
		public function rangedAngleBetween(pVector:ClEuclideanVector):Number
		{
			var firstA:Number, secondA:Number, a:Number;
			
			firstA = Math.atan2(pVector.position.y, pVector.position.x);
			secondA = Math.atan2(_position.y, _position.x);
			
			a = secondA - firstA;
			
			while( a > Math.PI)
				a -=Math.PI*2;
			while( a < -Math.PI )
				a += Math.PI*2;
			
			return a;
		}
		
		public function normalize():ClEuclideanVector
		{
			var m:Number = magnitude;
			_position.x /= m;
			_position.y /= m;
			
			return this;
		}
		
		public function normalRight():ClEuclideanVector
		{
			return new ClEuclideanVector(new Point(-position.y, position.x));
		}
		
		public function normalLeft():ClEuclideanVector
		{
			return new ClEuclideanVector(new Point(position.y, -position.x));
		}
		
		public function rotate( pAngleRadians:Number):ClEuclideanVector
		{
			var newPosX:Number = (position.x*Math.cos(pAngleRadians)) - (position.y * Math.sin(pAngleRadians));
			var newPosY:Number = (position.x * Math.sin(pAngleRadians)) + (position.y * Math.cos(pAngleRadians));
			
			_position.x = newPosX;
   			_position.y = newPosY;
 
    		return this;
		}
		
		// __________________________________________________________
		// -										 PRIVATES METHODS
		
		
		/* VAR */
		private var _position:Point;
	}
}
